package code801_900.code1_10;

/**
 * 在二维数组grid中，grid[i][j]代表位于某处的建筑物的高度。 我们被允许增加任何数量（不同建筑物的数量可能不同）的建筑物的高度。 高度 0 也被认为是建筑物。
 *
 * 最后，从新数组的所有四个方向（即顶部，底部，左侧和右侧）观看的“天际线”必须与原始数组的天际线相同。 城市的天际线是从远处观看时，由所有建筑物形成的矩形的外部轮廓。 请看下面的例子。
 *
 * 建筑物高度可以增加的最大总和是多少？
 *
 * 例子：
 * 输入： grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]
 * 输出： 35
 * 解释：
 * The grid is:
 * [ [3, 0, 8, 4],
 *   [2, 4, 5, 7],
 *   [9, 2, 6, 3],
 *   [0, 3, 1, 0] ]
 *
 * 从数组竖直方向（即顶部，底部）看“天际线”是：[9, 4, 8, 7]
 * 从水平水平方向（即左侧，右侧）看“天际线”是：[8, 7, 9, 3]
 *
 * 在不影响天际线的情况下对建筑物进行增高后，新数组如下：
 *
 * gridNew = [ [8, 4, 8, 7],
 *             [7, 4, 7, 7],
 *             [9, 4, 8, 7],
 *             [3, 3, 3, 3] ]
 *
 *
 */
public class _807maxIncreaseKeepingSkyline {

    /**
     * 思考：就一步一步的跟着步骤走。先确定行和列最大值的位置。
     * 再根据初始行和列填充其他行和列。每一cell中填写的值为min(row[i],col[j])
     *
     * 优化：看了题解后发现，确定初始行和列后，不需要填充其余每个cell，可以直接进行比较计算结果即可
     *
     * 执行用时：     * 1 ms     * , 在所有 Java 提交中击败了     * 83.37%     * 的用户
     * 内存消耗：     * 38 MB     * , 在所有 Java 提交中击败了     * 96.77%     * 的用户
     * @param grid
     * @return
     */
    public static int maxIncreaseKeepingSkyline(int[][] grid) {
        int[] row = new int[grid.length];
        int[] col = new int[grid[0].length];
        int rowMax = 0;
        int colMax = 0;
        int result = 0;
        // 找出每一行的最大值
        for (int i = 0; i < grid.length; i++) {
            rowMax = 0;
            for (int j = 0; j < grid[0].length; j++) {
                if(grid[i][j]>rowMax){
                    rowMax = grid[i][j];
                }
                row[i] = rowMax;
            }
        }
        // 找出每一列的最大值
        for (int i = 0; i < grid.length; i++) {
            colMax = 0;
            for (int j = 0; j < grid[0].length; j++) {
                if(grid[j][i]>colMax){
                    colMax = grid[j][i];
                }
                col[i] = colMax;
            }
        }
        // 寻找初始行列坐标，确定第一个行和列
        int[][] newArr = new int[grid.length][grid[0].length];
        int rowIndex = 0;
        int colIndex = 0;
        rowMax = 0;
        colMax = 0;
        for (int i = 0; i < row.length; i++) {
            if(rowMax<row[i]){
                rowMax = row[i];
                rowIndex = i;
            }
        }
        for (int i = 0; i < col.length; i++) {
            if(colMax<col[i]){
                colMax = col[i];
                colIndex = i;
            }
        }
        // 初始化新数组
        for (int i = 0; i < row.length; i++) {
            newArr[i][colIndex] = row[i];
        }
        for (int i = 0; i < col.length; i++) {
            newArr[rowIndex][i] = col[i];
        }
        // 构建新数组
        for (int i = 0; i < newArr.length; i++) {
            if(i == rowIndex){
                continue;
            }
            for (int j = 0; j < newArr[0].length; j++) {
                if(j != colIndex){
                    newArr[i][j] = row[i]<col[j]?row[i]:col[j];
                }
            }
        }
        // 计算最终结果
        for (int i = 0; i < newArr.length; i++) {
            for (int j = 0; j < newArr[0].length; j++) {
                result += (newArr[i][j]-grid[i][j]);
            }
        }
        return result;
    }

    public static void main(String[] args) {
        int[][] arr = {{84,25,79},{24,22,26},{87,93,87}};
        System.out.println(maxIncreaseKeepingSkyline(arr));
    }

    /**
     * 题解算法
     *
     * 执行用时：     * 1 ms     * , 在所有 Java 提交中击败了     * 83.37%     * 的用户
     * 内存消耗：     * 37.8 MB     * , 在所有 Java 提交中击败了     * 96.07%     * 的用户
     * @param grid
     * @return
     */
    public int maxIncreaseKeepingSkyline1(int[][] grid) {
        int n = grid.length;
        int[] rowMax = new int[n];
        int[] colMax = new int[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                rowMax[i] = Math.max(rowMax[i], grid[i][j]);
                colMax[j] = Math.max(colMax[j], grid[i][j]);
            }
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                ans += Math.min(rowMax[i], colMax[j]) - grid[i][j];
            }
        }
        return ans;
    }
}
